package com.ali.ttt.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author : yuxl
 * @create 2024/8/1 4:02 PM
 */
@Slf4j
@RestController
@RequestMapping("/api/completableFuture")
@Api(tags = "线程编排")
@AllArgsConstructor
public class CompletableFutureController {

    @GetMapping("/runAsync")
    @ApiOperation(value = "创建异步操作 runAsync")
    public void runAsync() {
        CompletableFuture
                .runAsync(() -> {
                    for (int i = 0; i < 3; i++) {
                        try {
                            TimeUnit.SECONDS.sleep(1);
                            log.info("线程1");
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
    }

    @GetMapping("/supplyAsync")
    @ApiOperation(value = "创建异步操作 supplyAsync")
    public Integer supplyAsync() throws ExecutionException, InterruptedException {
        return CompletableFuture
                .supplyAsync(() -> {
                    int n = 0;
                    for (int i = 0; i < 3; i++) {
                        try {
                            TimeUnit.SECONDS.sleep(1);
                            n++;
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    return n;
                }).whenComplete((s,e)->{
                    s +=1;
                }).get();
    }

    @GetMapping("/thenApply")
    @ApiOperation(value = "异步结果转换 thenApply")
    public Integer thenApply() throws ExecutionException, InterruptedException {
        return CompletableFuture.supplyAsync(() -> {
            return toInt(3);
        }).thenApply(number -> {
            return multiply(number,2);
        }).get();
    }

    @GetMapping("/thenCompose")
    @ApiOperation(value = "异步结果转换 thenCompose")
    public Integer thenCompose() throws ExecutionException, InterruptedException {
        return CompletableFuture.supplyAsync(() -> {
            return toInt(3);
        }).thenCompose(param -> CompletableFuture.supplyAsync(() -> {
            return multiply(param,2);
        })).get();
    }

    @GetMapping("/thenAccept")
    @ApiOperation(value = "异步结果消费 thenAccept")
    public Integer thenAccept() throws ExecutionException, InterruptedException {
        AtomicInteger i = new AtomicInteger();
        CompletableFuture.supplyAsync(() -> {
            return toInt(3);
        }).thenAccept(number -> {
            i.set(multiply(number, 2));
            log.info("结果为："+i.get());
        }).get();
        return i.get();
    }

    @GetMapping("/thenAcceptBoth")
    @ApiOperation(value = "异步结果消费 thenAcceptBoth")
    public Integer thenAcceptBoth() throws ExecutionException, InterruptedException {
        AtomicInteger i = new AtomicInteger();
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            return toInt(3);
        });
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            return toInt(2);
        });
        future1.thenAcceptBoth(future2, (x, y) -> {
            i.set(x + y);
            log.info("结果为：" + i.get());
        }).get();
        return i.get();
    }

    @GetMapping("/thenCombine")
    @ApiOperation(value = "结果组合 thenCombine")
    public Integer thenCombine() throws ExecutionException, InterruptedException {
        AtomicInteger i = new AtomicInteger();
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            return toInt(3);
        });
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            return toInt(2);
        });
        return future1.thenCombine(future2,(x,y)->{
            log.info("结果为："+i.get());
            return x + y;
        }).get();
    }

    @GetMapping("/allOf")
    @ApiOperation(value = "全部完成 allOf")
    public void allOf() throws ExecutionException, InterruptedException {
        AtomicInteger i = new AtomicInteger();
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            toInt(3);
        });
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            toInt(2);
        });
        CompletableFuture.allOf(future1, future2).get();
    }










    private Integer toInt(Integer n){
        try {
            TimeUnit.SECONDS.sleep(n);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return n;
    }
    private Integer multiply(Integer n1,Integer n2)  {
        try {
            TimeUnit.SECONDS.sleep(n2);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return n1 * n2;
    }

}
